#pragma once

#include "PKB.h"

// A PKB stub for unit testing of QueryEvaluator.
// Currently assumes the following SIMPLE source code:
// Procedure MyProc {
//1.	x = 2;
//2.	y = x;
//3.	while x {
//4.		x = x - 1;
//5.		y = y + x;
//6.		while y {
//7.			z = y - 1;
//			}
//		}
//8.	y = 5;
// }
// Currently implements the following STUB functions: 
// getParent, getParentStar, getChild, getChildStar
// 
// Assumes the following relationships:
// Parent(3,4), Parent(3,5), Prent(3,6), Parent(6,7)
// Modifies(1,"x"), Modifies(2,"y"), Modifies(4,"x"), Modifies(5,"y"), Modifies(7,"y"), Modifies(8,"y")
class PKBStubForParentTest : public PKB {
	private:

		typedef std::string ProcNameType;
		typedef std::string VarNameType;
		typedef Type::Entity::Line EntityType;

		std::map<int, TreeNode*> mAssignNodeMap;

		// Creates a tree for a line given the nodeType, varName and expr.
		// e.g. for a line like "x = y + z", use createTree(AST_ASSIGN, "x", "y+z")
		TreeNode* createTree(TreeNodeType nodeType, std::string varName, std::string expr);
		// Checks to see if subTree is indeed a subTree in mainTree.
		// If isPartialMatch is TRUE, then if subTree IS a subtree of mainTree, return true.
		// If isPartialMatch is FALSE, then return true IF AND ONLY IF subTree IS mainTree.
		bool isSubtree(TreeNode* mainTree, TreeNode* subTree, bool isPartialMatch);
	public:
		PKBStubForParentTest(void);
		~PKBStubForParentTest(void);
	
		// Currently assumes the following SIMPLE source code:
		// Procedure MyProc {
		//1.	x = 2;
		//2.	y = x;
		//3.	while x {
		//4.		x = x - 1;
		//5.		y = y + x;
		//6.		while y {
		//7.			z = y - 1;
		//			}
		//		}
		//8.	y = 5;
		// }
		virtual const Type::List::Line& getLinesByEntity(Type::Entity::Line);
		// Constants available: 1, 2, 5
		virtual const std::vector<int>& getConstants();
		// (varName = varIndex) Assumes:
		// x = 1, y = 2, z = 3.
		virtual Type::Index::Var getVarIndex(Type::Name::Var);
		// (varName = varIndex) Assumes:
		// x = 1, y = 2, z = 3.
		virtual std::vector<int> getVarIndexes();
		// (varName = varIndex) Assumes:
		// x = 1, y = 2, z = 3.
		virtual Type::Name::Var getVarName(Type::Index::Var);
		// Assumes the following Parent relationships:
		// Parent(3,4), Parent(3,5), Parent(3,6), Parent(6,7)
		// e.g. getParent(4) will return 3.
		virtual Type::Index::Line getParent(Type::Index::Line);
		// Assumes the following Parent* relationships:
		// Parent*(3,4), Parent*(3,5), Parent*(3,6), Parent*(3,7), Parent*(6,7)
		// e.g. getParentStar(7) will return a vector [3, 6].
		virtual Type::List::Line getParentStar(Type::Index::Line);
		// Assumes the following Parent relationships:
		// Parent(3,4), Parent(3,5), Parent(3,6), Parent(6,7)
		// e.g. getChild(3) will return a vector [4, 5, 6].
		virtual Type::List::Line getChild(Type::Index::Line);
		// Assumes the following Parent* relationships:
		// Parent*(3,4), Parent*(3,5), Parent*(3,6), Parent*(3,7), Parent*(6,7)
		// e.g. getChildStar(3) will return a vector [4, 5, 6, 7].
		virtual Type::List::Line getChildStar(Type::Index::Line);
		// Assumes the following Parent relationships:
		// Parent(3,4), Parent(3,5), Parent(3,6), Parent(6,7)
		// e.g. hasParent(4) returns true and hasParent(2) returns false.
		virtual bool hasParent(Type::Index::Line);
		// Assumes the following Parent relationships:
		// Parent(3,4), Parent(3,5), Parent(3,6), Parent(6,7)
		// e.g. hasChild(3) returns true and hasChild(4) returns false.
		virtual bool hasChild(Type::Index::Line);
		// Assumes the following Parent relationships:
		// Parent(3,4), Parent(3,5), Parent(3,6), Parent(6,7)
		// e.g. isParent(3,4) returns true and isParent(3,7) returns false.
		virtual bool isParent(Type::Index::Line,Type::Index::Line);
		// Assumes the following Parent* relationships:
		// Parent*(3,4), Parent*(3,5), Parent*(3,6), Parent*(3,7), Parent*(6,7)
		// e.g. isParentStar(3,7) returns true and isParent(3,8) returns false.
		virtual bool isParentStar(Type::Index::Line, Type::Index::Line);
		// Assumes the following Modifies relationships:
		// Modifies(1,"x"), Modifies(2,"y"), Modifies(4,"x"), Modifies(5,"y"), Modifies(7,"z"), Modifies(8,"y")
		// where (varName = varIndex) x = 1, y = 2, z = 3.
		// e.g. isLineModifies(1,1) returns true and isLineModifies(2,1) returns false.
		virtual bool isLineModifies(Type::Index::Line, Type::Index::Var);
		// Assumes the following Uses relationships:
		// Uses(2,"x"), Uses(3,"x"), Uses(4,"x"), Uses(5,"y"), Uses(5,"x"), Uses(6,"y"), Uses(7,"y")
		// where (varName = varIndex) x = 1, y = 2, z = 3.
		// e.g. isLineUses(3,1) returns true and isLineUses(6,1) returns false.
		virtual bool isLineUses(Type::Index::Line, Type::Index::Var);
		// Assumes the following Follows relationships:
		// Follows(1,2), Follows(2,3), Follows(3,8), Follows(4,5), Follows(5,6)
		// getFollows(1) will return 2.
		virtual Type::Index::Line getFollows(Type::Index::Line);
		// Assumes the following Follows relationships:
		// Follows*(1,2), Follows*(1,3), Follows*(1,8), Follows*(2,3), Follows*(2,8),
		// Follows*(3,8), Follows*(4,5), Follows*(4,6), Follows*(5,6)
		// getFollowStar(1) will return [2,3,8].
		virtual Type::List::Line getFollowStar(Type::Index::Line);
		// Assumes the following Follows relationships:
		// Follows(1,2), Follows(2,3), Follows(3,8), Follows(4,5), Follows(5,6)
		// getFollowedBy(2) will return 1. 
		virtual Type::Index::Line getFollowedBy(Type::Index::Line);
		// Assumes the following Follows relationships:
		// Follows*(1,2), Follows*(1,3), Follows*(1,8), Follows*(2,3), Follows*(2,8),
		// Follows*(3,8), Follows*(4,5), Follows*(4,6), Follows*(5,6)
		// getFollowedByStar(3) will return [1,3].
		virtual Type::List::Line getFollowedByStar(Type::Index::Line);
		// Assumes the following Follows relationships:
		// Follows(1,2), Follows(2,3), Follows(3,8), Follows(4,5), Follows(5,6)
		// isFollows(1,2) will return true, isFollows(3,4) will return false.
		virtual bool isFollows(Type::Index::Line, Type::Index::Line);
		// Assumes the following Follows relationships:
		// Follows*(1,2), Follows*(1,3), Follows*(1,8), Follows*(2,3), Follows*(2,8),
		// Follows*(3,8), Follows*(4,5), Follows*(4,6), Follows*(5,6)
		// isFollowStar(3,8) will return true, isFollowStar(3,4) will return false.
		virtual bool isFollowStar(Type::Index::Line, Type::Index::Line);
		// Assumes the following (ASSIGN ONLY) patterns:
		// 1 a("x","2"), 2 a("y","x"), 4 a("x","x-1"), 5 a("y","y+x"), 7 a("z","y-1"), 8 a("y","5")
		// where (varName = varIndex) x = 1, y = 2, z = 3.
		virtual Type::List::Line getLineIndexForPattern(PatternType patternType, Type::Index::Var varIndex, TreeNode* exprRoot, bool isPartialMatch);
};

